package com.grj.service.redis.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.grj.service.redis.entity.Kills;
import com.grj.service.redis.entity.Orders;
import com.grj.service.redis.service.KillsService;
import com.grj.service.redis.mapper.KillsMapper;
import com.grj.service.redis.service.MyService;
import com.grj.service.redis.service.OrdersService;
import io.lettuce.core.RedisClient;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
* @author 14505
* @description 针对表【kills】的数据库操作Service实现
* @createDate 2023-12-19 04:34:23
*/
@Service
public class KillsServiceImpl extends ServiceImpl<KillsMapper, Kills>
    implements KillsService{


    @Resource
    private  KillsService killsService;
    @Resource
    private OrdersService ordersService;

    @Resource
    private RedisIdWorker redisIdWorker;
    @Resource
    private HttpServletResponse httpServletResponse;

    @Resource
    private HttpServletRequest httpServletRequest;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private RedissonClient redissonClient;


    @Override
    public Boolean kill(Long id, Long i) {
        Kills byId = killsService.getOne(new LambdaQueryWrapper<Kills>().eq(Kills::getVoucherId, id));
        if(byId == null || byId.getVoucherId() == null){
            System.out.println("没有该券");
            return false;
        }
        if(new DateTime(byId.getBeginTime()).isAfter(new Date())){
            System.out.println("还没开始");
            return false;
        }
        if(new DateTime(byId.getEndTime()).isBefore(new Date())){
            System.out.println("已经结束");
            return false;
        }


//        synchronized(Long.toString(uid).intern()){
//            KillsService k = (KillsService) AopContext.currentProxy();
//            return k.buy(1L);
//        }

        Long uid = i;
        RLock lock = redissonClient.getLock("order:"+ uid);
        System.out.println("当前线程:" + Thread.currentThread().getName());
        //加锁
        try {
            if (!lock.tryLock(1, TimeUnit.SECONDS)) {
                String message = "线程:" + Thread.currentThread().getName() + "未获取到锁,直接返回";
                System.out.println(message);
                return null;
            }
            System.out.println("线程:" + Thread.currentThread().getName() + "获取到锁!");
            KillsService k = (KillsService) AopContext.currentProxy();
            return k.buy(1L, uid);
        } catch (InterruptedException e) {
            throw new RuntimeException(String.format("出现异常：%s",e.getMessage()));
        } finally {
            //判断 拿到了锁的才释放锁,否则会报错!
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                System.out.println("线程:" + Thread.currentThread().getName() + "释放锁!");
                lock.unlock();
            }
        }



    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean buy(long l, Long uid) {
        long count = ordersService.count(new LambdaQueryWrapper<Orders>().eq(Orders::getVid, l).eq(Orders::getUid, 1L));
        if(count > 0){
            System.out.println("已经购买过");
            return false;
        }

        boolean update = killsService.update(new LambdaUpdateWrapper<Kills>().setSql("stock = stock -1").gt(Kills::getStock, 0).eq(Kills::getVoucherId, l));
        if(!update){
            System.out.println("库存不足");
            return false;
        }
        Orders orders = new Orders();
        orders.setId(redisIdWorker.nextId("order"));
        orders.setUid(uid);
        orders.setVid(l);
        ordersService.save(orders);
        System.out.println("成功");
        System.out.println("线程:" + Thread.currentThread().getName() + "业务结束!");
        return true;
    }

}




